package com.magupe.im.web.handler;

import com.magupe.im.web.db.service.DataService;
import com.magupe.im.web.handler.http.HttpAccessHandler;
import com.magupe.im.web.handler.websocket.WebsocketAccessHandler;
import com.magupe.im.web.handler.websocket.WebsocketGroupMessageHandler;
import com.magupe.im.web.handler.websocket.WebsocketIdleStateProcessHandler;
import com.magupe.im.web.handler.websocket.WebsocketMessageHandler;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPipeline;
import io.netty.handler.codec.ByteToMessageDecoder;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import io.netty.util.CharsetUtil;

import java.util.List;
import java.util.concurrent.TimeUnit;

public class ProtocolSelectorHandler extends ByteToMessageDecoder{

    /**
     * websocket定义请求行前缀
     */
    private static final String WEBSOCKET_LINE_PREFIX = "GET /cheetah";

    private DataService dataService;

    public ProtocolSelectorHandler(DataService dataService){
        this.dataService = dataService;
    }

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception{
        if (isWebSocketUrl(byteBuf)) {
            addWebSocketHandlers(ctx.pipeline());
        } else if (isCustomProtocol(byteBuf)) {
            addTCPProtocolHandlers(ctx.pipeline());
        } else {
            addHTTPHandlers(ctx.pipeline());
        }
        ctx.pipeline().remove(this);
    }

    /**
     * 是否有websocket请求行前缀
     *
     * @param byteBuf
     * @return
     */
    private boolean isWebSocketUrl(ByteBuf byteBuf) {
        if (byteBuf.readableBytes() < WEBSOCKET_LINE_PREFIX.length()) {
            return false;
        }
        byteBuf.markReaderIndex();

        byte[] content = new byte[WEBSOCKET_LINE_PREFIX.length()];
        byteBuf.readBytes(content);
        byteBuf.resetReaderIndex();

        String str = new String(content, CharsetUtil.UTF_8);
        return str.equals(WEBSOCKET_LINE_PREFIX);
    }

    /**
     * 是否是自定义协议
     *
     * @param byteBuf
     * @return
     */
    private boolean isCustomProtocol(ByteBuf byteBuf) {
        return false;
    }

    /**
     * 动态添加WebSocket处理器
     *
     * @param pipeline
     */
    private void addWebSocketHandlers(ChannelPipeline pipeline) {
        pipeline.addLast(new HttpServerCodec());						// websocket协议本身是基于http协议的，所以这边也要使用http解编码器
        pipeline.addLast(new ChunkedWriteHandler());					// 以块的方式来写的处理器
        pipeline.addLast(new HttpObjectAggregator(8192));				// netty是基于分段请求的，HttpObjectAggregator的作用是将请求分段再聚合,参数是聚合字节的最大长度

        //websocket定义了传递数据的6中frame类型
        pipeline.addLast(new IdleStateHandler(80, 80, 400, TimeUnit.SECONDS));
        pipeline.addLast(new WebsocketIdleStateProcessHandler());
        pipeline.addLast(new WebsocketAccessHandler(dataService));
        pipeline.addLast(new WebsocketMessageHandler(dataService));
        pipeline.addLast(new WebsocketGroupMessageHandler(dataService));
    }

    /**
     * 动态添加TCP私有协议处理器
     *
     * @param pipeline
     */
    private void addTCPProtocolHandlers(ChannelPipeline pipeline) {

    }

    /**
     * 动态添加HTTP处理器
     *
     * @param pipeline
     */
    private void addHTTPHandlers(ChannelPipeline pipeline) {
        pipeline.addLast(new HttpServerCodec());
        pipeline.addLast(new HttpObjectAggregator(8192));
        pipeline.addLast(new HttpAccessHandler());
    }
}
